home *** CD-ROM | disk | FTP | other *** search
/ Gigarom 1 / Gigarom Macintosh Archives (Quantum Leap)(CDRM1080320)(1993).iso / FILES / BBS / MUBBS / MUBBS etc.cpt / Module Source / Serial Module code / serial module.c < prev    next >
Text File  |  1991-11-21  |  13KB  |  472 lines

  1. /*
  2.  *  Serial Module.c
  3.  *
  4.  *    This program source code and it's compiled version is
  5.  *  Copyright (c) 1991 N. Hawthorn.
  6.  *  This program source code and it's compiled version IS NOT IN THE
  7.  *  PUBLIC DOMAIN ! Please read the "COPYRIGHT NOTICE / NH" file for details
  8.  *  regarding use of this program source code and it's compiled version.
  9.  *
  10.  *  This module's name is "serial", it's type is "MOD1", usea resource mover
  11.  *  to assign a new number to it, that's why we name our modules !
  12.  *
  13.  *  THIS IS A INIT MODULE, IT NEEDS TO BE IN LISTED IN THE "INITMODULES" LIST
  14.  *  It only needs to be called as a INIT, it just sets up the serial I/O pointers
  15.  *
  16.  *  Notice that we use "Hook Stuff.h" and we do not just "return", but jump to
  17.  *  "end" and there set the A4 register before returning.
  18.  *
  19.  */
  20.  
  21. #define INMAIN
  22.  
  23. #include     <SetUpA4.h>
  24. #include    "MUBBS Module.h"
  25. #include "Hook Stuff.h"
  26. #include <SerialDvr.h>
  27. #include <DeviceMgr.h>
  28. #include <FileMgr.h>
  29.  
  30. /*
  31. #define    AinRefNum    (-6)  ; just for info
  32. #define    AoutRefNum    (-7)
  33. #define    BinRefNum    (-8)
  34. #define    BoutRefNum    (-9)
  35. */
  36.  
  37. #define SWITCHNOW 5        /* max times of not switching before a force switch */
  38.  
  39. /* my globals for this module */
  40.  
  41. static char    inbuffA[1024], /* the serial read buffer locked down */
  42.             inbuffB[1024]; /* the serial read buffer locked down */
  43.  
  44.  
  45. pascal void main (mode1,G1,P1)
  46.        int mode1;
  47.        struct GS *G1;
  48.        Ptr P1; /* we ignore "P" in this module */
  49. {
  50. Handle temph;
  51. float version = 0.5; /* what version of MUBBS you are compatable with IE: .5 and above */
  52. RememberA0(); SetUpA4(); /* This sets up the A4 register to access our globals */
  53. asm { _RecoverHandle }; asm {move.l a0,temph}; HLock(temph); /* locks our module, do this ! */
  54.  
  55. G=G1; /* This MUST be the first thing you do in main only, it sets up the struct globals */
  56. mode[u]=mode1; /* set up our mode so that you can read it anywhere */
  57.  
  58. storeA4(); /* save the value of A4 for later calls, only in this type of SPECIAL module */
  59.  
  60. switch (mode[u]) { /* any un-handled modes return error from this module */
  61.  
  62.     case 98: /* NOTE that this DOESN'T unlock */
  63.         versionck(version); /* just return after this call, don't modify anything */
  64.         goto skip1;        /* DON'T UNLOCK */
  65.         break;        
  66.     case 0:
  67.         strcpy (G->programmer,"N Hawthorn"); /* show the programmer's name up to 20 chars*/
  68.         setpointers();    /* init call, set up the pointers now */
  69.         G->moduleresult=99; /* we put 99 here because we need to be called to CLOSE */
  70.         goto skip1;        /* DON'T UNLOCK */
  71.         break;
  72.     case 1:
  73.         G->moduleresult=0; /* bye bye call, UNLOCK NOW */
  74.         break;
  75.     default:
  76.         G->moduleresult=1; /* return bad code */
  77.     };
  78.  
  79. HUnlock(temph); /* unlocks this module, do this ! */
  80.  
  81. skip1:
  82. RestoreA4(); /* call this when you are all done */
  83. }
  84.  
  85.  
  86. sOpen1 () {
  87.  
  88. static SerShk *handshake;
  89. int serConfig, serBlen;
  90. int err;
  91.  
  92. getA4();
  93.  
  94. if (u == G->localuser || u > 1) goto end; /* don't open if it's the local user */
  95.  
  96. if (u==0) {
  97. if (err = RAMSDOpen(sPortA)) {
  98.     print("\nC> ERROR ! Cannot open the serial driver A\n");
  99.     }
  100.  
  101. print("<serial driver A opened> ");
  102. serConfig=data8+stop10+noParity;
  103. if (strcmp(G->userbaud[u],"300") == 0) serConfig=serConfig+baud300;
  104. if (strcmp(G->userbaud[u],"1200") == 0) serConfig=serConfig+baud1200;
  105. if (strcmp(G->userbaud[u],"2400") == 0) serConfig=serConfig+baud2400;
  106. if (strcmp(G->userbaud[u],"9600") == 0) serConfig=serConfig+baud9600;
  107. if (strcmp(G->userbaud[u],"19200") == 0) serConfig=serConfig+baud19200;
  108. if (err = SerReset(AinRefNum, serConfig)) print("\n ERROR ! calling serial config A\n");
  109.  
  110. handshake->fXOn = 0;        /* no XON/XOFF output flow control */
  111. handshake->fCTS = 0;        /* no CTS (input) hardware handshake */
  112. handshake->xOn  = 0x00;        /* XON character */
  113. handshake->xOff = 0x00;        /* XOFF character */
  114. handshake->errs = 0;        /* Ignore input errors */
  115. handshake->evts = 0;        /* No device driver events */
  116. handshake->fInX = 0;        /* no XON/XOFF input flow control */
  117. handshake->fDTR = 0;        /* no DTR (output) hardware handshake */
  118.  
  119. if (err = SerHShake(AinRefNum, handshake)) print("\nERROR !  calling serialHShake A\n");
  120. serBlen = 2048; /* set the buffer length */
  121.  
  122. if (err = SerSetBuf(AinRefNum, &inbuffA, serBlen)) print("\nERROR ! setting up serial buffer A\n");
  123.  
  124. print("<serial port A configed >\n");
  125. }
  126.  
  127. if (u==1) {
  128. if (err = RAMSDOpen(sPortB)) {
  129.     print("\nERROR ! Cannot open the serial driver B\n");
  130.     }
  131.  
  132. print("<serial driver B opened> ");
  133. serConfig=data8+stop10+noParity;
  134. if (strcmp(G->userbaud[u],"300") == 0) serConfig=serConfig+baud300;
  135. if (strcmp(G->userbaud[u],"1200") == 0) serConfig=serConfig+baud1200;
  136. if (strcmp(G->userbaud[u],"2400") == 0) serConfig=serConfig+baud2400;
  137. if (strcmp(G->userbaud[u],"9600") == 0) serConfig=serConfig+baud9600;
  138. if (strcmp(G->userbaud[u],"19200") == 0) serConfig=serConfig+baud19200;
  139. if (err = SerReset(BinRefNum, serConfig)) print("\nERROR !  calling serial config B\n");
  140.  
  141. handshake->fXOn = 0;        /* no XON/XOFF output flow control */
  142. handshake->fCTS = 0;        /* no CTS (input) hardware handshake */
  143. handshake->xOn  = 0x00;        /* XON character */
  144. handshake->xOff = 0x00;        /* XOFF character */
  145. handshake->errs = 0;        /* Ignore input errors */
  146. handshake->evts = 0;        /* No device driver events */
  147. handshake->fInX = 0;        /* no XON/XOFF input flow control */
  148. handshake->fDTR = 0;        /* no DTR (output) hardware handshake */
  149.  
  150. if (err = SerHShake(BinRefNum, handshake)) print("\nERROR !  calling serialHShake B\n");
  151. serBlen = 2048; /* set the buffer length */
  152.  
  153. if (err = SerSetBuf(BinRefNum, &inbuffB, serBlen)) print("\nERROR !  setting up serial buffer B\n");
  154.  
  155. print("<serial port B configed >\n");
  156. }
  157. end:
  158. getoldA4();
  159. }
  160.  
  161.  
  162. sClose1 () {
  163. getA4();
  164. if (u == G->localuser) goto end; /* don't close if it's the local user */
  165. if (u==0) RAMSDClose(sPortA);
  166. if (u==1) RAMSDClose(sPortB);
  167. print("C> <serial driver %d closed>\n",u);
  168. end:
  169. getoldA4();
  170. }
  171.  
  172. sin1()   /* Returns a character from serial port */
  173. {
  174. int keylen,result;
  175. Byte check; /* used to check the CTS line */
  176. char buffer[2]; /* a temp buffer for input storage */
  177. CntrlParam contb; /* the blocks of bytes to do I/O */
  178. IOParam iob;
  179.  
  180. getA4();
  181.  
  182. if (G->local[u]) {
  183.     if (keylen = strlen(G->keyboardbuf) > 0) { /* are there characters waiting ? */
  184.         G->input[u]=G->keyboardbuf[(keylen-1)];
  185.         G->keyboardbuf[(keylen-1)] = 0; /* shorten the string */
  186.         result=TRUE;
  187.         otheruser(FALSE); /* switch if it's time to switch */
  188.         goto end;
  189.         }
  190.     goto none;
  191.     }
  192.  
  193. if (u != G->localuser) {
  194. /* some addresses for my info ($9FFFFA) or $50F04022 */
  195.  
  196. if (u == 0) {
  197.     if (G->carrdet[u] && (check = *(SCCRd + 2) & 0x20)) { /* CTS is bit 5, 1= carr loss */
  198.         print("C>             CARRIER LOSS DETECTED DURING INPUT !!\n");
  199.         G->online[u]=FALSE;
  200.         goto none;
  201.         }
  202.     contb.ioRefNum = AinRefNum;
  203.     contb.csCode = 2;                   /* do a status to see if any chars */
  204.     if (PBStatus(&contb, FALSE)) goto none;
  205.     if (*(long *)&contb.csParam[0]) { /* do the check for characters */
  206.         iob.ioRefNum = AinRefNum;
  207.         iob.ioBuffer = (Ptr)buffer; /* characters waiting, get them */
  208.         iob.ioReqCount = 1;
  209.         if (PBRead(&iob, FALSE)) goto none;
  210.         if (G->nottransfer[u]) {G->input[u] = buffer[0] & 0x7F;} /* strip the 8th bit for text */
  211.         else G->input[u] = buffer[0]; /* G->input[u] is a global variable */
  212.         otheruser(FALSE); /* once and a while switch */
  213.         result=TRUE;
  214.         goto end;
  215.         }
  216.     goto none;
  217.     }
  218.  
  219. if (u == 1) {
  220.     if (G->carrdet[u] && (check = *(SCCRd + 0) & 0x20)) { /* CTS is bit 5, 1= carr loss */
  221.         print("C>             CARRIER LOSS DETECTED DURING INPUT !!\n");
  222.         G->online[u]=FALSE;
  223.         goto none;
  224.         }
  225.     contb.ioRefNum = BinRefNum;
  226.     contb.csCode = 2;                   /* do a SerGetBuf to see if any chars */
  227.     if (PBStatus(&contb, FALSE)) goto none;
  228.     if (*(long *)&contb.csParam[0]) { /* do the check for characters */
  229.         iob.ioRefNum = BinRefNum;
  230.         iob.ioBuffer = (Ptr)buffer; /* characters waiting, get them */
  231.         iob.ioReqCount = 1;
  232.         if (PBRead(&iob, FALSE)) goto none;
  233.         if (G->nottransfer[u]) {G->input[u] = buffer[0] & 0x7F;} /* strip the 8th bit for text */
  234.         else G->input[u] = buffer[0]; /* G->input[u] is a global variable */
  235.         otheruser(FALSE); /* once and a while switch */
  236.         result=TRUE;
  237.         goto end;
  238.         }
  239.     }
  240. } /* close the "BIG" if */
  241.  
  242. none:
  243. otheruser(TRUE); /* switch NOW, don't wait when we arn't doing anything */
  244. result=FALSE; /* no characters waiting */
  245.  
  246. end:
  247. getoldA4();
  248. return result;
  249. }
  250.  
  251. sout1(x)  /* sends a character to serial port */
  252. unsigned char x;
  253. {
  254. int result;
  255. char buffer[2]; /* a temp buffer for input storage */
  256. Byte check; /* used to check the CTS line */
  257. IOParam iob;
  258.  
  259. getA4();
  260.  
  261. if (G->monitor[u]) {if (x != 0x0A) printout(x);} /* for monitoring */
  262.  
  263. iob.ioCompletion = 0L; /* set these up now */
  264. iob.ioBuffer = (Ptr)buffer;
  265. iob.ioReqCount = 1;
  266.  
  267. loop:
  268. if ( u != G->localuser) {
  269.     if (u == 0) {
  270.         if ( !G->nocheck[u] ){
  271.             if (G->carrdet[u] && (check = *(SCCRd + 2) & 0x20)) { /* CTS is bit 5, 1= carr loss */
  272.                 print("C>             CARRIER LOSS DETECTED DURING ** OUTPUT ** !!\n");
  273.                 G->cancel[u]=TRUE;
  274.                 G->online[u]=FALSE;
  275.                 goto none;
  276.                 }
  277.             }
  278.         while(TRUE) {
  279.             if (check = *(SCCRd + 2) & 0x04) break; /* Tx Empty is bit 2, 1= empty */
  280.             otheruser(TRUE); /* switch now, we arn't doing nothin */
  281.             }
  282.         buffer[0]=x;
  283.         iob.ioRefNum = AoutRefNum;
  284.         PBWrite(&iob, TRUE);        /* asynchronous */
  285.         otheruser(FALSE); /* make sure we switch once and a while */
  286.         result=TRUE;
  287.         goto end;
  288.         }
  289.  
  290.     if (u == 1) {
  291.         if ( !G->nocheck[u] ){
  292.             if (G->carrdet[u] && (check = *(SCCRd + 0) & 0x20)) { /* CTS is bit 5, 1= carr loss */
  293.                 print("C>             CARRIER LOSS DETECTED DURING ** OUTPUT ** !!\n");
  294.                 G->cancel[u]=TRUE;
  295.                 G->online[u]=FALSE;
  296.                 result=FALSE;
  297.                 goto end;
  298.                 }
  299.             }
  300.         while(TRUE) {
  301.             if (check = *(SCCRd + 0) & 0x04) break; /* Tx Empty is bit 2, 1= empty */
  302.             otheruser(TRUE); /* switch now, we arn't doing nothin */
  303.             }
  304.         buffer[0]=x;
  305.         iob.ioRefNum = BoutRefNum;
  306.         PBWrite(&iob, TRUE);        /* asynchronous */
  307.         otheruser(FALSE); /* make sure we switch once and a while */
  308.         result=TRUE;
  309.         goto end;
  310.         }
  311.     }
  312. otheruser(FALSE); /* if it's the local user, we did print, so it's OK */
  313. result=TRUE;
  314. goto end;
  315.  
  316. none:
  317. otheruser(TRUE); /* switch now if we arn't doing anything */
  318. result=FALSE;
  319.  
  320. end:
  321. getoldA4();
  322. return result;
  323. }
  324.  
  325. sflush1 () /* reads all input data until none avail */
  326. {
  327. IOParam iob;
  328.  
  329. getA4();
  330.  
  331. if (G->local[u]) {
  332.     G->keyboardbuf[0]=0; /* reset keyboard buffer */
  333.     G->input[u]=0;
  334.     goto end;
  335.     }
  336.  
  337. if (u == G->localuser || u > 1) goto end; /* don't do it if it's the local user */
  338.  
  339. if (u == 0) {
  340.     iob.ioRefNum = AinRefNum;
  341.     iob.ioCompletion = 0;
  342.     PBKillIO(&iob, FALSE);
  343.     G->input[u]=0; /* clear the old data */
  344.     }
  345. if (u == 1) {
  346.     iob.ioRefNum = BinRefNum;
  347.     iob.ioCompletion = 0;
  348.     PBKillIO(&iob, FALSE);
  349.     G->input[u]=0; /* clear the old data */
  350.     }
  351.  
  352. end:
  353. otheruser(FALSE);
  354. getoldA4();
  355. }
  356.  
  357. out1(x)
  358. unsigned char x;
  359. {
  360. Byte i;
  361. int a,c,result;
  362.  
  363. getA4();
  364.  
  365. result=TRUE;
  366. G->cancel[u]=FALSE;
  367. if (G->nottransfer[u]){
  368.     if ( !G->nocheck[u] ){
  369.         if (sin1()){
  370.             if ((G->input[u] & 0x1F) == 0x13) { /* CTL S, S, 3 and s */
  371.                 sflush1();
  372.                 in1(); /* wait for another keypress, if none, continue anyway */
  373.                 sflush1();
  374.                 }
  375.             else {
  376.                 if ((G->input[u] & 0x1F) == 0x03) { /* ctl C, C, # and c */
  377.                     sflush1();
  378.                     G->cancel[u]=TRUE; /* return showing that we have been canceled */
  379.                     }
  380.                 }
  381.             }
  382.         if (x == 0x0A) { /* look for the LF after a CR */
  383.             if (G->userlines[u] && !G->cont[u]) { /* if it's not 0 */
  384.                 if (++G->linecnt[u] >= G->userlines[u]){
  385.                     sout1(x); /* do the LF now */
  386.                     c = G->input[u]; /* save the old input value */
  387.                     G->linecnt[u] = 1; /* reset the line count */
  388.                     cmd1noecho("Cancel, No (pause):"); /* NO ECHO HERE !! */
  389.                     i = G->input[u];
  390.                     if (i == 'C' || i == 'c') {G->cancel[u]=TRUE;} /* cancel the output */
  391.                     if (i == 'N' || i == 'n') {G->cont[u]=TRUE;}
  392.                     a=0;
  393.                     while (a++ < 19) {
  394.                         sout1('\b');
  395.                         sout1(' ');
  396.                         sout1('\b');
  397.                         } /* get rid of line */
  398.                     G->input[u] = c; /* return the old input value */
  399.                     G->linecnt[u] = 1; /* reset the line count */
  400.                     goto end; /* skip the output */
  401.                     }
  402.                 }
  403.             }
  404.         }
  405.     }
  406. result=sout1(x);
  407. end:
  408. getoldA4();
  409. return result;
  410. }
  411.  
  412. in1() /* returns true if a character is waiting, false for timeout */
  413. {
  414. long int time1;
  415. int warn,result;
  416. Byte check; /* used to check the CTS line */
  417.  
  418. getA4();
  419.  
  420. time1=Time;
  421. warn=0;
  422. if (G->local[u]) showline(); /* show the whole line line now, on the mac screen */
  423.  
  424. inloop: /* it will return like a time out if carrier is lost */
  425.  
  426. if ( ! sin1()) { /* if it's zero (no character) then */
  427.     if(!G->online[u]) {
  428.         result=FALSE;
  429.         goto end;
  430.         }
  431.     if (G->chatmode[u] > 0) { /* are we being chatted ??
  432.         if(!module(2,"chat",0L) G->chatmode[u]=0; /* call the chat module */
  433.         time1=Time; /* RESET the clock !! */
  434.         }
  435.     if ((Time-time1)<G->maxtime[u] ) goto inloop;
  436.     warn++;
  437.     time1=Time;
  438.     if (warn == 1) send("]Warning #1 inactivity timeout in %d seconds..]",(G->maxtime[u]*2));
  439.     if (warn == 2) send("]WARNING #2 INACTIVITY TIMEOUT IN %d SECONDS !!]",G->maxtime[u]);
  440.     if (warn == 3) {
  441.         send("]** INACTIVITY TIMEOUT, AUTO LOG OUT IN PROGRESS **]");
  442.         G->online[u]=FALSE;
  443.         result=FALSE;
  444.         goto end;
  445.         }
  446.     goto inloop;
  447.     };
  448. result=TRUE;
  449.  
  450. end:
  451. getoldA4();
  452. return result;
  453. }
  454.  
  455.  
  456. setpointers(){ /* that's all this does ! */
  457.  
  458. G->seropen = sOpen1;
  459. G->serclose = sClose1;
  460. G->serin = sin1;
  461. G->serout = sout1;
  462. G->serflush = sflush1;
  463. G->in = in1;
  464. G->out = out1;
  465.  
  466. /* block serial in / out will go here when implimented */
  467.  
  468. }
  469.  
  470.  
  471.  
  472.